local f = CreateFrame"Frame"
local dropdown, dropdownInit = CreateFrame( "Frame", "AraBrokerMoneyDD", nil, "UIDropDownMenuTemplate" )
local player = UnitName"player"
local tipshown, config, days, chars, classes, f1, f2, f3
local t, sorted, defaultClass = {}, {}, { r=1, g=.8, b=0 }
local ByMoney = function(a,b) return a.money > b.money end
local ByName = function(a,b) return a.name < b.name end
local othersMoney, session, today = 0
local RAID_CLASS_COLORS = CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS

local block = LibStub("LibDataBroker-1.1"):NewDataObject("|cFFFFB366Ara|r Money", {
	type = "data source",
	icon = "Interface\\Minimap\\Tracking\\Auctioneer",
	OnLeave = function()
		GameTooltipTextLeft1:SetFont( f1, f2, f3 )
		GameTooltipTextRight1:SetFont( f1, f2, f3 )
		tipshown = nil
		return GameTooltip:Hide()
	end,
	OnClick = function(self, button)
		if button == "RightButton" then
			GameTooltip:Hide()
			UIDropDownMenu_Initialize( dropdown, dropdownInit, "MENU" )
			return ToggleDropDownMenu( 1, nil, dropdown, self, 0, 0)
		end
	end
})

local function sortChars(func)
	for k, v in next, sorted do
		t[#t+1], sorted[k], v.name, v.money = v
	end
	for k, v in next, chars do
		local i = tremove(t) or {}
		sorted[#sorted+1], i.name, i.money = i, k, v
	end
	sort( sorted, func )
	return sorted
end

local modes = { "full", "compact", "longText", "midText", "shortText", "color", "dotColor" }

local function GetMoneyText(money, mode)
	return	mode == "full" and ( money < 0 and "-"..GetCoinTextureString(-money, 0) or GetCoinTextureString(money, 0) ) or
		mode == "compact" and floor(money*.0001) or
		mode == "longText" and (
			(money>9999 or money<-9999) and format("%i|cffffd700g|r %.2i|cffc7c7cfs|r %.2i|cffeda55fc|r", floor(money*.0001), floor(money*.01)%100, money%100 ) or
			(money > 99 or money<  -99) and format("%i|cffc7c7cfs|r %.2i|cffeda55fc|r", floor(money*.01), money%100 ) or
			format("%i|cffeda55fc|r", money) ) or
		mode == "midText" and format("%.2f|cffffd700g|r", money*.0001) or
		mode == "shortText" and format("%i|cffffd700g|r", floor(money*.0001) ) or
		(money>9999 or money<-9999) and format(mode=="color"and"|cffffd700%i|r |cffc7c7cf%.2i|r |cffeda55f%.2i|r"or"|cffffd700%i|r.|cffc7c7cf%.2i|r.|cffeda55f%.2i|r", floor(money*.0001), floor(money*.01)%100, money%100 ) or
		(money > 99 or money<  -99) and format(mode=="color"and"|cffc7c7cf%i|r |cffeda55f%.2i|r"or"|cffc7c7cf%i|r.|cffeda55f%.2i|r", floor(money*.01), money%100 ) or
		format("|cffeda55f%i|r", money),
		money <= 0 and 1 or 0, money < 0 and 0 or 1, 0, 1,1,1
end

block.OnEnter = function(self)
	tipshown = self
	local showBelow = select(2, self:GetCenter()) > UIParent:GetHeight()/2
	GameTooltip:SetOwner( self, "ANCHOR_NONE" )
	GameTooltip:SetPoint( showBelow and "TOP" or "BOTTOM", self, showBelow and "BOTTOM" or "TOP" )

	local total, mode = othersMoney + chars[player], config.tipMode
	GameTooltip:AddDoubleLine( "Session",	GetMoneyText( total	   - session, mode ) )
	GameTooltip:AddDoubleLine( "Today",	GetMoneyText( total	   - days[today], mode ) )
	GameTooltip:AddDoubleLine( "Yesterday",	GetMoneyText( days[today]  - days[today-1], mode ) )
	GameTooltip:AddDoubleLine( "This Week",	GetMoneyText( total	   - days[today-6], mode ) )
	if days[today-29] then
		GameTooltip:AddDoubleLine( "This Month",GetMoneyText( total - days[today-29], mode ) )
	end
	GameTooltip:AddLine" "

	for _, char in ipairs(sortChars(ByMoney)) do
		local class = RAID_CLASS_COLORS[classes[char.name]] or defaultClass
		GameTooltip:AddDoubleLine( char.name, GetMoneyText(char.money, mode), class.r, class.g, class.b, 1,1,1 )
	end
	GameTooltip:AddDoubleLine( "\nTotal", "\n"..GetMoneyText(total, mode), 1,.8,0, 1,1,1 )

	f1, f2, f3 = GameTooltipTextLeft1:GetFont()
	GameTooltipTextLeft1:SetFont( GameTooltipTextLeft2:GetFont() )
	GameTooltipTextRight1:SetFont( GameTooltipTextLeft2:GetFont() )
	return GameTooltip:Show()
end

local function OnEvent(self, event, addon)
	if event ~= "ADDON_LOADED" then
		if not days then return end
		local currentMoney = GetMoney()
		local d = date("*t") -- :'3
		today = (d.year-1970)*365+d.yday+floor((d.year-1973)/4) -- r9
		if not days[today] then
			local oldestDay, oldestMoney = today, othersMoney + currentMoney
			for day, money in next, days do
				if day < oldestDay then oldestDay, oldestMoney = day, money end
			end
			for day, money in next, days do
				if day < today-29 then
					if day > oldestDay then oldestDay, oldestMoney = day, money end
					days[day] = nil
				end
			end
			for i=today-29, today-1 do
				if days[i] then oldestMoney = days[i] else days[i] = oldestMoney end
			end
			days[today] = othersMoney + ( chars[player] or currentMoney )
		end
		chars[player] = currentMoney
		if not session then session = othersMoney + currentMoney end
		block.text = GetMoneyText(currentMoney, config.mode)
		return tipshown and block.OnEnter(tipshown)
	elseif addon ~= "Ara_Broker_Money" then return end

	AraBrokerMoneyDB = AraBrokerMoneyDB or {}
	config = AraBrokerMoneyDB
	config.mode = config.mode or "full" -- r5
	config.tipMode = config.tipMode or "longText" -- r6
	local realm = GetRealmName()
	config[realm] = config[realm] or { days={}, chars={} }
	realm = config[realm]
	realm.classes = realm.classes or {}
	days, chars, classes = realm.days, realm.chars, realm.classes
	for k, v in next, chars do
		if k~=player then othersMoney = othersMoney + v end
	end
	classes[player] = select(2,UnitClass"player")
	return IsLoggedIn() and OnEvent(nil, "")
end

f:SetScript( "OnEvent", OnEvent )

f:RegisterEvent"ADDON_LOADED"
f:RegisterEvent"PLAYER_LOGIN"
f:RegisterEvent"PLAYER_MONEY"
f:RegisterEvent"PLAYER_TRADE_MONEY"
f:RegisterEvent"TRADE_MONEY_CHANGED"
f:RegisterEvent"SEND_MAIL_MONEY_CHANGED"
f:RegisterEvent"SEND_MAIL_COD_CHANGED"

local function RemoveChar(_, char)
	othersMoney, chars[char], classes[char] = othersMoney - chars[char]
	print( "[|cffffb366Ara|rBrokerMoney] Character |cff40ff40"..char.."|r has been removed." )
end

local function SetMode(_, type, mode)
	config[type] = mode
	if type == "mode" then
		block.text = GetMoneyText(chars[player], mode)
	end
end

local options = {
 	{ text = "|cFFFFB366Ara|r Broker Money ("..GetAddOnMetadata( "Ara_Broker_Money", "Version" )..")", isTitle = true },
	{ text = "Block display mode...",	submenu = "mode" },
	{ text = "Tooltip display mode...",	submenu = "tipMode" },
	{ text = "Remove data from...",		submenu = "chars" }
}

dropdownInit = function(self, level)
	level = level or 1
	local items, info = level > 1 and UIDROPDOWNMENU_MENU_VALUE or options
	local table = items=="chars" and sortChars(ByName) or (items=="mode" or items=="tipMode") and modes or items
	for _, v in ipairs(table) do
		if not v.name or v.name ~= player then
			info = UIDropDownMenu_CreateInfo()
			if items == "mode" or items == "tipMode" then
				info.checked = config[items] == v
				info.text = GetMoneyText(chars[player], v)
				info.func, info.arg1, info.arg2 = SetMode, items, v
			else
				info.text, info.hasArrow, info.value, info.isTitle = v.text, v.submenu, v.submenu, v.isTitle
				if items == "chars" then
					info.func, info.arg1 = RemoveChar, v.name
					local class = RAID_CLASS_COLORS[classes[v.name]] or defaultClass
					info.text = format("|cff%.2x%.2x%.2x%s|r  ("..GetMoneyText(chars[v.name], config.mode)..")",
						class.r*255, class.g*255, class.b*255, v.name)
				end
			end
			UIDropDownMenu_AddButton( info, level )
		end
	end
end